fix(desktop): explicit bot opens and session creates dial the pool at foreground priority - #113269
Merged
Merged
Conversation
…t/retainGatewayForAgent and the session-create dials The #102281/#104139 chain tagged every activation-door dial (openGatewayForAgent/openGatewayForProfile/ensureGatewayForAgent/ sharedPrimaryRoute) as 'foreground' so a user-initiated open takes the pool's reserved slot instead of queuing behind background roster hydration. requestGatewayForAgent and retainGatewayForAgent never got a spawnPriority, so they always dialed 'background', and they are the only dial path createBackendSessionForSend (first send on a fresh chat) and openNewSessionTile ("New session" / tab-strip "+") use. On a saturated 3-slot local pool the user's first message or new-tab click could wait out the background slot timeout. Add `{ spawnPriority }` options (main's requestGatewayForProfile shape, 5eb0ed4) to both functions and forward it into every dial they make: requestGatewayForProfile on the scope===key and primary-registry branches, isAttachedSharedRemote, openSecondary, and the plain-profile retain branch's gatewayForProfile(key, true, ...) which neither #105390 nor #110354 covered. The four session-create call sites pass 'foreground'. Tests: gateway-spawn-priority.test.ts gains both polarities for request/retain plus the plain-profile retain branch; the use-session-actions and default-new-session matchers pin the tagged dial. SpawnPriority is now exported for the SDK.
….requestProfile options Clicking a bot in the roster runs findExistingCanonicalChat -> requestForBot(bot, 'session.list') -> host.requestProfile(route, ...) -> requestGatewayForAgent with no intent, so the first RPC of the gesture, the one that cold-spawns the bot's backend on a local pool, dialed 'background'. With three roster backends already hydrating the click produced no backend activity and the fail-closed lookup surfaced as a "try again" toast (#105104). The later host.openSession is already foreground, but it never runs until this lookup returns. host.requestProfile gains a fifth `options?: { spawnPriority }` argument; `timeoutMs` stays the fourth positional so no existing caller changes shape, and the SDK keeps its exact call arity when no options are given. requestForBot takes the same options and forwards them only when set, so passive roster warming (profiles.list, ui_meta) still dials background. The canonical `session.list` and the `session.create` that follows on a first-ever open both pass 'foreground'. Tests: profile-routing.test.ts (options form with and without a timeout), routing.test.ts (tag forwarded, untagged call keeps three args), canonical-chat-registry.test.ts (session.list and session.create carry foreground; session.title does not).
This was referenced Sep 16, 2026
Contributor
૮ >ﻌ< ა ci reviewran on 338d833 — fix(desktop): canonical Bot Chat lookup dials foreground thr debug infoCI timingsCI timings · View report · View jobWall time 4m14s vs 6m43s (-37.0%). 2 job(s) slower, 3 faster, 1 unchanged.
|
13 tasks
Open
15 tasks
QuixThe2nd
pushed a commit
to QuixThe2nd/hermes-ide
that referenced
this pull request
Sep 17, 2026
…creates dial the pool at foreground priority (NousResearch#113269)
9 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Symptom
#105104: clicking a bot in the roster intermittently does nothing. No backend activity, then a "try again" toast. On the same 3-slot local pool, the first send on a fresh chat and "New session" / tab-strip "+" could wait out the background slot timeout while roster hydration held every slot.
What was happening, per layer
#102281 / #104139 tagged the activation doors (
openGatewayForAgent,openGatewayForProfile,ensureGatewayForAgent,sharedPrimaryRoute) as foreground, and5eb0ed4531gaverequestGatewayForProfilea{ spawnPriority }options object. Two RPC paths never got it:apps/desktop/src/store/gateway.ts:1026 requestGatewayForAgentand:1229 retainGatewayForAgenthad no priority parameter. TheirisAttachedSharedRemoteprobe,openSecondaryconnect, and bothrequestGatewayForProfileforwards dialed background.retainGatewayForAgent's plain-profile branch (gatewayForProfile(key, true)) too; neither salvaged PR covered that one.apps/desktop/src/app/session/hooks/use-session-actions/index.ts:604,612(createBackendSessionForSend) and:824,832(openNewSessionTile) are the only callers of that pair for a session create, and they passed nothing.apps/desktop/src/plugins/hermes-bots/canonical-chat.ts:245requestForBot(bot, 'session.list')->routing.ts:213 host.requestProfile(route, method, params)->sdk/index.ts:249 requestGatewayForAgent(...). The click's first RPC, the one that cold-spawns the bot's backend, carried no intent. The laterhost.openSessionis already foreground but never runs until this lookup returns.Fix, per layer
gateway.ts:requestGatewayForAgent(..., timeoutMs?, signal?, { spawnPriority = 'background' } = {})andretainGatewayForAgent(connectionId, profile, { spawnPriority = 'background' } = {}), same options shape asrequestGatewayForProfile. Forwarded into bothrequestGatewayForProfilebranches,isAttachedSharedRemote,openSecondary, andgatewayForProfile(key, true, spawnPriority).SpawnPriorityis exported for the SDK.use-session-actions/index.ts: the four create-path calls pass{ spawnPriority: 'foreground' }; the retain is the first dial so it carries the tag too.sdk/index.ts:host.requestProfile(route, method, params, timeoutMs?, options?: { spawnPriority }).timeoutMsstays positional so no existing caller changes shape, and the SDK keeps its exact call arity when options are absent (the pool tests pin that). JSDoc onrequestProfiledocuments the choice.hermes-bots/routing.ts:requestForBot(bot, method, params, options?)forwardsspawnPriorityonly when set.canonical-chat.ts: the canonicalsession.listand thesession.createon a first-ever open pass'foreground'. Passive roster warming (profiles.list,ui_meta) still dials background.Tests
Both polarities at each layer, converted from the PRs' change-detectors into behaviour contracts:
store/gateway-spawn-priority.test.ts: request/retain tagged -> every registry dial carriespriority: 'foreground'; untagged -> no priority key; retain on the plain-profile (null connection) route dials foreground.sdk/profile-routing.test.ts: options form with a timeout and without one; the existing numeric-timeout and no-timeout tests still pin the old arity.plugins/hermes-bots/routing.test.ts: tag forwarded as the fifth arg; an untagged call keeps three args.plugins/hermes-bots/canonical-chat-registry.test.ts:session.listandsession.createcarry the tag,session.titledoes not.use-session-actions.test.tsx,default-new-session.test.tsx: create matchers pin the tagged dial and the tagged retain.Red on base: with the five production files stashed and the tests kept, 9 failed / 187 passed across the five touched test files (all nine are the new foreground assertions; the negative-polarity tests pass on base as expected). Green after: 196/196.
npx vitest run src/store src/sdk src/plugins/hermes-bots src/app/session: 3173 passed, the 2 failures arevoice-prefs.test.ts, pre-existing onmain.npm run typecheckclean;npx eslinton the touched files: 0 errors.Not fixed here
Closes #105104: this is one layer of that symptom.Supersedes #110354, #105390.
Thanks @jxfjosh: the diagnosis that the canonical lookup's
session.listis the click's first dial, and that it had to go throughhost.requestProfile, is the centre of the second commit. Thanks @nftpoetrist: the observation thatrequestGatewayForAgent/retainGatewayForAgentwere the one untagged dial pair left after #102281, and that the retain must be tagged as well as the create, is the first commit. Both are credited as commit authors.